{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Translating from Qubiter to Xanadu PennyLane\n",
    "\n",
    "The purpose of this notebook is to illustrate how to translate a Qubiter English file for\n",
    "a quantum circuit, into a Xanadu Pennylane \"qnode\"\n",
    "\n",
    "Next, we will create 2 Qubiter English files and then translate them to Pennylanese "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "First change your working directory to the qubiter directory in your computer, and add its path to the path environment variable."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "/home/rrtucci/PycharmProjects/qubiter/qubiter/jupyter_notebooks\n",
      "/home/rrtucci/PycharmProjects/qubiter\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "import sys\n",
    "print(os.getcwd())\n",
    "os.chdir('../../')\n",
    "print(os.getcwd())\n",
    "sys.path.insert(0,os.getcwd())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next we create a Qubiter English file and its corresponding Picture file."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "loaded OneQubitGate, WITHOUT autograd.numpy\n"
     ]
    }
   ],
   "source": [
    "from qubiter.device_specific.Qubiter_to_PennyLane import *"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "file_prefix = \"qbtr2penny_test1\"\n",
    "num_qbits = 3\n",
    "emb = CktEmbedder(num_qbits, num_qbits)\n",
    "wr = SEO_writer(file_prefix, emb)\n",
    "wr.write_H(0)\n",
    "wr.write_X(1)\n",
    "wr.write_Y(1)\n",
    "wr.write_Z(1)\n",
    "wr.write_cnot(0, 1)\n",
    "wr.write_cz(0, 1)\n",
    "wr.write_qbit_swap(1, 0)\n",
    "wr.write_Rx(2, rads=np.pi)\n",
    "wr.write_Ry(2, rads=np.pi)\n",
    "wr.write_Rz(2, rads=np.pi)\n",
    "wr.write_one_qbit_gate(1, OneQubitGate.P_1_phase_fac, [np.pi])\n",
    "wr.write_Rn(0, rads_list=[np.pi, np.pi, np.pi])\n",
    "wr.close_files()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<table style='font-family:monospace'><tr><td style='border-right:1px solid red;'>1</td><td style='text-align:left;'><pre>HAD2\tAT\t0</pre></td></tr><td style='border-right:1px solid red;'>2</td><td style='text-align:left;'><pre>SIGX\tAT\t1</pre></td></tr><td style='border-right:1px solid red;'>3</td><td style='text-align:left;'><pre>SIGY\tAT\t1</pre></td></tr><td style='border-right:1px solid red;'>4</td><td style='text-align:left;'><pre>SIGZ\tAT\t1</pre></td></tr><td style='border-right:1px solid red;'>5</td><td style='text-align:left;'><pre>SIGX\tAT\t1\tIF\t0T</pre></td></tr><td style='border-right:1px solid red;'>6</td><td style='text-align:left;'><pre>SIGZ\tAT\t1\tIF\t0T</pre></td></tr><td style='border-right:1px solid red;'>7</td><td style='text-align:left;'><pre>SWAP\t1\t0</pre></td></tr><td style='border-right:1px solid red;'>8</td><td style='text-align:left;'><pre>ROTX\t180.000000\tAT\t2</pre></td></tr><td style='border-right:1px solid red;'>9</td><td style='text-align:left;'><pre>ROTY\t180.000000\tAT\t2</pre></td></tr><td style='border-right:1px solid red;'>10</td><td style='text-align:left;'><pre>ROTZ\t180.000000\tAT\t2</pre></td></tr><td style='border-right:1px solid red;'>11</td><td style='text-align:left;'><pre>P1PH\t180.000000\tAT\t1</pre></td></tr><td style='border-right:1px solid red;'>12</td><td style='text-align:left;'><pre>ROTN\t180.000000\t180.000000\t180.000000\tAT\t0</pre></td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "wr.print_eng_file(jup=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<table style='font-family:monospace'><tr><td style='border-right:1px solid red;'>1</td><td style='text-align:left;'><pre>|   |   H</pre></td></tr><td style='border-right:1px solid red;'>2</td><td style='text-align:left;'><pre>|   X   |</pre></td></tr><td style='border-right:1px solid red;'>3</td><td style='text-align:left;'><pre>|   Y   |</pre></td></tr><td style='border-right:1px solid red;'>4</td><td style='text-align:left;'><pre>|   Z   |</pre></td></tr><td style='border-right:1px solid red;'>5</td><td style='text-align:left;'><pre>|   X---@</pre></td></tr><td style='border-right:1px solid red;'>6</td><td style='text-align:left;'><pre>|   Z---@</pre></td></tr><td style='border-right:1px solid red;'>7</td><td style='text-align:left;'><pre>|   <---></pre></td></tr><td style='border-right:1px solid red;'>8</td><td style='text-align:left;'><pre>Rx  |   |</pre></td></tr><td style='border-right:1px solid red;'>9</td><td style='text-align:left;'><pre>Ry  |   |</pre></td></tr><td style='border-right:1px solid red;'>10</td><td style='text-align:left;'><pre>Rz  |   |</pre></td></tr><td style='border-right:1px solid red;'>11</td><td style='text-align:left;'><pre>|   @P  |</pre></td></tr><td style='border-right:1px solid red;'>12</td><td style='text-align:left;'><pre>|   |   R</pre></td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "wr.print_pic_file(jup=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next we translate this to a single PennyLane qnode called Turing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<qubiter.device_specific.Qubiter_to_PennyLane.Qubiter_to_PennyLane at 0x7f7804847390>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "aqasm_name = 'PennyL'\n",
    "qnode_name = 'Turing'\n",
    "Qubiter_to_PennyLane(file_prefix, num_qbits,\n",
    "        qnode_name,\n",
    "        aqasm_name=aqasm_name,\n",
    "        write_qubiter_files=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The following 3 files were generated by the constructor just called:\n",
    "\n",
    "1. <a href='../io_folder/qbtr2penny_test1_X1_3_eng.txt'>../io_folder/qbtr2penny_test1_X1_3_eng.txt</a>\n",
    "2. <a href='../io_folder/qbtr2penny_test1_X1_3_ZLpic.txt'>../io_folder/qbtr2penny_test1_X1_3_ZLpic.txt</a>\n",
    "3. <a href='../io_folder/qbtr2penny_test1_PennyL.py'>../io_folder/qbtr2penny_test1_PennyL.py</a>\n",
    "\n",
    "Files 1 and 2 are Qubiter style English and Picture files (they differ from the input English file principally in that they include more NOTA lines).\n",
    "\n",
    "File 3 is the PennyLane file that we wanted. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " This first example\n",
    "has no placeholder variables. It just shows that most PennyLane gates are supported."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next we create another Qubiter English file and its corresponding Picture file."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "file_prefix = \"qbtr2penny_test2\"\n",
    "num_qbits = 4\n",
    "emb = CktEmbedder(num_qbits, num_qbits)\n",
    "wr = SEO_writer(file_prefix, emb)\n",
    "wr.write_Rx(2, rads=np.pi/7)\n",
    "wr.write_Rx(1, rads='#2*.5')\n",
    "wr.write_Rn(3, rads_list=['#1', '-#1*3', '#2'])\n",
    "wr.write_Rx(1, rads='-my_fun#2#1')\n",
    "wr.write_cnot(2, 3)\n",
    "wr.close_files()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<table style='font-family:monospace'><tr><td style='border-right:1px solid red;'>1</td><td style='text-align:left;'><pre>ROTX\t25.714286\tAT\t2</pre></td></tr><td style='border-right:1px solid red;'>2</td><td style='text-align:left;'><pre>ROTX\t#2*.5\tAT\t1</pre></td></tr><td style='border-right:1px solid red;'>3</td><td style='text-align:left;'><pre>ROTN\t#1\t-#1*3\t#2\tAT\t3</pre></td></tr><td style='border-right:1px solid red;'>4</td><td style='text-align:left;'><pre>ROTX\t-my_fun#2#1\tAT\t1</pre></td></tr><td style='border-right:1px solid red;'>5</td><td style='text-align:left;'><pre>SIGX\tAT\t3\tIF\t2T</pre></td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "wr.print_eng_file(jup=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<table style='font-family:monospace'><tr><td style='border-right:1px solid red;'>1</td><td style='text-align:left;'><pre>|   Rx  |   |</pre></td></tr><td style='border-right:1px solid red;'>2</td><td style='text-align:left;'><pre>|   |   Rx  |</pre></td></tr><td style='border-right:1px solid red;'>3</td><td style='text-align:left;'><pre>R   |   |   |</pre></td></tr><td style='border-right:1px solid red;'>4</td><td style='text-align:left;'><pre>|   |   Rx  |</pre></td></tr><td style='border-right:1px solid red;'>5</td><td style='text-align:left;'><pre>X---@   |   |</pre></td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "wr.print_pic_file(jup=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next we translate this to a single PennyLane qnode called Feynman.\n",
    "This time, the English file uses a placeholder function called `my_fun`.\n",
    "All placeholder functions must be\n",
    "defined beforehand in a file and the\n",
    "path to that file must be specified via the variable `fun_defs_path`.\n",
    "In this example, `my_fun` is defined in the following file\n",
    "\n",
    "<a href='../io_folder/qbtr2penny_test2_fun_defs.py'>../io_folder/qbtr2penny_test2_fun_defs.py</a>\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<qubiter.device_specific.Qubiter_to_PennyLane.Qubiter_to_PennyLane at 0x7f780483eb10>"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "aqasm_name = 'PennyL'\n",
    "fun_defs_path = 'qbtr2penny_test2_fun_defs.py'\n",
    "qnode_name = 'Feynman'\n",
    "Qubiter_to_PennyLane(file_prefix, num_qbits,\n",
    "        qnode_name,\n",
    "        fun_defs_path,\n",
    "        aqasm_name=aqasm_name,\n",
    "        write_qubiter_files=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The following 3 files were generated by the constructor just called:\n",
    "\n",
    "1. <a href='../io_folder/qbtr2penny_test2_X1_4_eng.txt'>../io_folder/qbtr2penny_test2_X1_4_eng.txt</a>\n",
    "2. <a href='../io_folder/qbtr2penny_test2_X1_4_ZLpic.txt'>../io_folder/qbtr2penny_test2_X1_4_ZLpic.txt</a>\n",
    "3. <a href='../io_folder/qbtr2penny_test2_PennyL.py'>../io_folder/qbtr2penny_test2_PennyL.py</a>\n",
    "\n",
    "Files 1 and 2 are Qubiter style English and Picture files (they differ from the input English file principally in that they include more NOTA lines).\n",
    "\n",
    "File 3 is the PennyLane file that we wanted. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Notice that\n",
    "* the argument of gate QubitUnitary() calls the function rot(). This function is\n",
    "defined internally in the qnode. The translating software automatically copies the def of rot() from\n",
    "the file `OneQubitGate.py` where it is defined.\n",
    "* the argument of one of the RX() rotations calls the function my_fun(). This function is defined\n",
    "internally in the qnode too. The translating software automatically copies the def of my_fun() from\n",
    "the file at `fun_defs_path`\n",
    "* We haven't specified what type of object the Hamiltonian hamil is. Ideally, I would like the constructor `Hermitian` to accept a hamil which is an object of the class QubitOperator from the open-source library OpenFermion.\n",
    "\n",
    "I haven't tested yet whether this qnode works\n",
    "in PennyLane, with Rigetti's hardware and with Tensorflow or PyTorch  \n",
    "\n",
    "This is a particularly demanding test of PennyLane, but I\n",
    "will consider PennyLane **incomplete** until and unless it can handle this qnode,\n",
    "or some alternative that accomplishes the same goals.\n",
    "Incomplete because I feel this qnode uses features that are possible to code and that most users \n",
    "of Pennylane will want to have them. Tensorflow's back-propagation should be able to\n",
    "reach inside the user supplied functions my_fun() and rot(),\n",
    "although the code defining those functions might need some superficial modifications like replacing the `np.` by something else"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  },
  "toc": {
   "colors": {
    "hover_highlight": "#DAA520",
    "running_highlight": "#FF0000",
    "selected_highlight": "#FFD700"
   },
   "moveMenuLeft": true,
   "nav_menu": {
    "height": "51px",
    "width": "252px"
   },
   "navigate_menu": true,
   "number_sections": true,
   "sideBar": true,
   "threshold": 4,
   "toc_cell": false,
   "toc_section_display": "block",
   "toc_window_display": false,
   "widenNotebook": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
